home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************************
- *
- *
- * ObjectMacZapp -- a standard Mac OOP application template
- *
- *
- *
- * ZProgress.cpp -- a progress dialog
- *
- *
- *
- *
- *
- * © 1996, Graham Cox
- *
- *
- *
- *
- *************************************************************************************************/
-
- #include "ZProgress.h"
- #include "MacZoop.h"
-
- extern ZCommander* gCurHandler;
-
- /*-----------------------------*** CONSTRUCTOR ***------------------------------------*/
-
- // this is an alternative constructor to set the striped/proportional mode explicitly, or
- // you can use the other constructor passing a negative value to default to striped mode.
-
-
- ZProgress::ZProgress( ZCommander* aBoss,
- const short dialogID,
- const long maxValue,
- const short pType,
- const ProgType aMode )
- : ZDialog( aBoss, dialogID )
- {
- theType = pType;
-
- // max should not be less than 1 to avoid potential divide by zero error
-
- max = MAX( 1, ( maxValue & 0x7FFFFFFF ));
-
- // if maxValue is negative, default to indeterminate progress. Otherwise use whatever
- // was passed along in the <aMode> parameter.
-
- if ( maxValue & 0x80000000 )
- displayMode = kIndeterminateProgress;
- else
- displayMode = aMode;
-
- value = 0;
- deferTime = 0;
- createTime = TickCount();
- fAbort = FALSE;
- SetRect( &pRect, 0, 0, 0, 0 );
-
- stripesPat = GetPixPat( kStdStripedPattern );
-
- InitZWindow();
- }
-
-
- /*------------------------------*** DESTRUCTOR ***------------------------------------*/
-
- ZProgress::~ZProgress()
- {
- Hide();
-
- // remove the stripes pattern if present
-
- if ( stripesPat )
- DisposePixPat( stripesPat );
-
- // this type of dialog is not usually closed from outside, but is simply
- // destroyed. In this case we need to make sure the chain of command is
- // maintained correctly. We can't call Close since that deletes the object
- // creating an infinite loop. Thus we simply manipulate the handler directly.
-
- if ( gCurHandler == this ) // make the current handler this
- gCurHandler = itsBoss; // one's boss- i.e. the application
- }
-
- /*---------------------------------*** SETUP ***--------------------------------------*/
- /*
-
- overrides ZDialog to set up the button and bar according to the type
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::SetUp()
- {
- // set up the text of the button to the requested type of dialog
-
- short iType;
- Handle iHand;
- Rect iBox;
-
- if ( theType == kNoButton )
- {
- HideDialogItem( macWindow, kCancelButton );
-
- // extend the length of the bar in this case so that it is properly
- // centred in the dialog window. (Looks better).
-
- GetDialogItem( macWindow, kBarItem, &iType, &iHand, &iBox );
-
- iBox.right = macWindow->portRect.right - iBox.left;
- SetDialogItem( macWindow, kBarItem, iType, iHand, &iBox );
- }
- else
- {
- // the button is visible, but maybe its text is different.
- // By default it is Cancel, but may need to say "Stop"
-
- if ( theType == kStopType )
- {
- Str31 stopStr;
-
- GetDialogItem(macWindow, kCancelButton, &iType, &iHand, &iBox);
-
- // sanity check- this IS a control, isn't it?
-
- if ( iType & ctrlItem )
- {
- GetIndString( stopStr, 128, kStopStringID );
- SetControlTitle(( ControlHandle ) iHand, stopStr );
- }
- }
- }
-
- // call inherited SetUp in case base class wants to do something
-
- inherited::SetUp();
- }
-
- /*---------------------------------*** DRAW ***---------------------------------------*/
- /*
- refresh the dialog
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::Draw()
- {
- SetRect( &pRect, 0, 0, 0, 0 );
- inherited::Draw();
- }
-
-
- /*-----------------------------*** DRAWUSERITEM ***-----------------------------------*/
- /*
-
- Draws the progress bar user item
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::DrawUserItem( const short item )
- {
- // override to draw the progress bar user-item. This is also called directly when
- // InformProgress is called to update the bar.
-
- if ( item == kBarItem )
- {
- short iType, barLength;
- Handle iHand;
- Rect iBox, barBox;
- PixPatHandle backPP, forePP;
-
- GetDialogItem( macWindow, item, &iType, &iHand, &iBox );
- FrameRect( &iBox );
-
- #ifdef _GREYSCALE_APPEARANCE
-
- FrameGrayRect( &iBox );
-
- #endif
- InsetRect( &iBox, 1, 1 );
-
- // if this is a striped bar, all we do is cycle the stripe and
- // repaint it.
-
- if ( displayMode == kIndeterminateProgress )
- {
- if ( stripesPat )
- {
- CycleStripe();
- FillCRect( &iBox, stripesPat );
- }
- else
- InvertRect( &iBox ); // not a great deal we can do if no resources...
- }
- else
- {
- // compute the size of the barBox, based on max and value
-
- barLength = (short)(((double) value / (double) max) * (long)( iBox.right - iBox.left ));
- barBox = iBox;
- barBox.right = MIN( barBox.left + barLength, iBox.right );
-
- // if this is different to the previously calculated bar, repaint it
-
- if (! EqualRect( &pRect, &barBox ))
- {
- try
- {
- // if this is the first update, pRect will be empty, so
- // simply fill in the background
-
- if ( EmptyRect( &pRect ))
- {
- FailNIL( backPP = GetPixPat( kStdBackPattern ));
- FillCRect( &iBox, backPP );
- DisposePixPat( backPP );
- }
-
- FailNIL( forePP = GetPixPat( kStdBarPattern ));
- FillCRect( &barBox, forePP );
- DisposePixPat( forePP );
- }
- catch ( OSErr err )
- {
- // if the patterns don't exist, paint the bar instead.
-
- PaintRect( &barBox );
-
- // do not propagate exceptions from here
- }
-
- // update pRect if the window is visible.
-
- if ( IsVisible())
- pRect = barBox;
- }
- }
- }
- else
- inherited::DrawUserItem( item );
- }
-
-
- /*-------------------------------*** CLICKITEM ***------------------------------------*/
- /*
- set the abort flag if the user clicked cancel or stop
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::ClickItem( const short theItem )
- {
- fAbort = ( theItem == kCancelButton );
- }
-
-
- /*-----------------------------*** INFORMPROGRESS ***---------------------------------*/
- /*
- called to keep the progress dialog moving as a lengthy operation proceeds
- ----------------------------------------------------------------------------------------*/
-
- Boolean ZProgress::InformProgress( const long progressSoFar )
- {
- CGrafPtr savePort;
- GDHandle saveDevice;
-
- // save the current port and device in case we were called from
- // some function that had changed it. Note that the caller should be
- // aware that the port, device, etc MAY not be exactly preserved
- // across calls to this, since this processes events, etc.
-
- GetGWorld( &savePort, &saveDevice );
- SetGDevice( GetMainDevice());
-
- // update the value we have got to here
-
- value = progressSoFar;
-
- // if it is time to show the progress dialog, make it visible
-
- if (( TickCount() > ( createTime + deferTime )) && !IsVisible())
- Select();
-
- // let the application handle any pending event, so we get updated, etc. etc
- // any exceptions arising are handled by the caller. Note that in the
- // event of an exception, the device is set to the main device, which
- // is possibly safer, though if the caller knows different, it should
- // try to do the right thing.
-
- gApplication->Process1Event();
-
- // redraw the progress bar
-
- Focus();
- DrawUserItem( kBarItem );
-
- // restore what we think is the port and device
-
- SetGWorld( savePort, saveDevice );
-
- return !fAbort; // carry on until this flag is set
- }
-
-
- /*--------------------------------*** SETDELAY ***------------------------------------*/
- /*
- set the initial deferment delay
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::SetDelay( const short delayTicks )
- {
- deferTime = delayTicks;
- }
-
-
- /*-------------------------------*** SETMESSAGE ***-----------------------------------*/
- /*
- set the message string to the string passed
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::SetMessage( const Str255& aMsg )
- {
- SetValue( kMessageItem, aMsg );
- }
-
-
- /*-------------------------------*** SETMESSAGE ***-----------------------------------*/
- /*
- set the message to the STR# resource with ID and index passed
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::SetMessage( const short resID, const short index )
- {
- Str255 aStr;
-
- GetIndString( aStr, resID, index );
- SetMessage( aStr );
- }
-
-
- /*---------------------------------*** SETMODE ***------------------------------------*/
- /*
- switch from stripey to proportional and back
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::SetMode( ProgType aMode )
- {
- if ( aMode != displayMode )
- {
- displayMode = aMode;
-
- // force a re-draw of the whole bar
-
- Draw();
- }
- }
-
-
- /*----------------------------------*** FILTER ***------------------------------------*/
- /*
- maps command-period to the cancel/stop button, unless a kNoButton type
- ----------------------------------------------------------------------------------------*/
-
- Boolean ZProgress::Filter( EventRecord* theEvent )
- {
- Boolean fullyHandled = FALSE;
-
- if ( theType != kNoButton )
- {
- if ( theEvent->what == keyDown )
- {
- char theKey = theEvent->message & charCodeMask;
-
- if ((theKey == '.') &&
- ((theEvent->modifiers & cmdKey) == cmdKey))
- {
- FakeClick( kCancelButton );
-
- fullyHandled = TRUE;
- }
- }
- }
-
- return fullyHandled;
- }
-
-
- /*-------------------------------*** CYCLESTRIPE ***----------------------------------*/
- /*
- for stripe bar, this moves the pattern by <loop>, animating it. This is designed to be called
- repeatedly, and only changes the pattern every few (3, in this case) ticks.
- ----------------------------------------------------------------------------------------*/
-
- void ZProgress::CycleStripe()
- {
- if ( stripesPat && IsVisible())
- {
- // see if it is time yet. Notethat this function re-uses the timing
- // data members, but since they are only used before the dialog is visible,
- // this is OK in this particular case.
-
- deferTime = TickCount();
-
- if ( deferTime > ( createTime + 3 ))
- {
- createTime = deferTime;
-
- // modify the pattern. We do this by copying the
- // image data of the pattern to itself in another
- // position, based on the pixmap dimensions.
-
- long patImgSize;
- short rowBytes, loop = 2;
- Ptr tempBuffer;
-
- rowBytes = (*(*stripesPat)->patMap)->rowBytes & 0x3FFF;
- patImgSize = GetHandleSize((*stripesPat)->patData );
-
- // copy the top row of the data into a temporary buffer
- // that we create. This holds one row of image data.
-
- tempBuffer = NewPtr( rowBytes );
-
- do
- {
- BlockMoveData(*(*stripesPat)->patData, tempBuffer, rowBytes);
-
- // copy the rest of the data up one row
-
- BlockMoveData((*(*stripesPat)->patData) + rowBytes, *(*stripesPat)->patData, patImgSize - rowBytes);
-
- // copy the temp row to the bottom of the image
-
- BlockMoveData(tempBuffer, (*(*stripesPat)->patData) + patImgSize - rowBytes, rowBytes);
- }
- while (--loop);
-
- DisposePtr( tempBuffer );
- PixPatChanged( stripesPat );
- }
- }
- }
-
-